/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package DTD;

import Excepciones.InvalidReadException;
import Utilidades.Coleccion;
import Utilidades.LectorXML;
import Utilidades.StrOp;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
/**
 *
 * @author Administrador
 */
public class LectorDTD {
    private LectorXML xmlReader;
    private String[] dtdInterna;
    private String[] dtdExterna;

    public LectorDTD(LectorXML xmlReader) throws FileNotFoundException, InvalidReadException {
        this.xmlReader = xmlReader;
        cargarRegla();
    }

    public String[] getReglasExternas() {
        return dtdExterna;
    }

    public String[] getReglasInternas() {
        return dtdInterna;
    }

    private void cargarRegla() throws FileNotFoundException, InvalidReadException {
        boolean esFinal = false;
        boolean esInicioReglaInterna = false;
        boolean esFinalReglaInterna  = false;
        char aux = ' ';
        String regla = "";

        while (!esFinal) {
            try {
                aux = xmlReader.getChar();
            } catch (IOException ex) {
                esFinal = true;
            }// try

            if (aux == '[') {
                esInicioReglaInterna = true;
            }
            else if (esInicioReglaInterna && aux == ']') {
                esFinalReglaInterna = true;
            }
            else if (esFinalReglaInterna && aux == '>') {
                esFinal = true;
            }
            else if (!esInicioReglaInterna && aux == '>') {
                esFinal = true;
            }
            regla += String.valueOf(aux);
        }//while
        cargarReglaExterna(regla);
        cargarReglaInterna(regla);
        validar(regla);
    }

    private String[] borrarVacias(String[] aBorrar) {
        ArrayList<String> resultado = new ArrayList<String>();

        for (int i = 0; i < aBorrar.length; i++) {
            String regla = aBorrar[i];
            if (regla != null && regla.trim().equals("")==false) {
                resultado.add(regla);
            }
        }
        return resultado.toArray(new String[resultado.size()]);
    }

    private void validar(String regla) throws InvalidReadException {
        String msg = "";
        int iSystem = regla.indexOf("SYSTEM");
        int iPublic = regla.indexOf("PUBLIC");
        int iInterna = regla.indexOf("[");

        if (iPublic != -1 && iSystem != -1) {
            msg += "No puede existir SYSTEM y PUBLIC en el mismo doctype.\n";
        }
        if (iSystem != -1 && this.dtdExterna.length < 1) {
            msg += "El archivo DTD externo está vacio\n";
        }
        if (iInterna != -1 && this.dtdInterna.length < 1) {
            msg += "El archivo DTD interno está vacio\n";
        }
        if (!msg.equals("")) {
            throw new InvalidReadException(msg, this);
        }
    }

    private void cargarReglaExterna(final String regla) throws FileNotFoundException {
        String path = "";
        int iSystem = regla.indexOf("SYSTEM");
        int iPublic = regla.indexOf("PUBLIC");

        if (iSystem != iPublic) {
            ArrayList<String> vector = new ArrayList<String>();
            int iInicioPath = regla.indexOf("\"");
            int iFinalPath = regla.indexOf("\"", iInicioPath + 1);
            path = regla.substring(iInicioPath, iFinalPath).trim();
            path = path.replaceAll("\"", "");
            LectorXML exReader = new LectorXML(path);
            String externalRead = "";

            do {
                externalRead = exReader.getNext();
                if (externalRead != null) {
                    vector.add(externalRead);
                }
            } while (externalRead != null);

            exReader.close();
            this.dtdExterna = vector.toArray(new String[vector.size()]);
            this.dtdExterna = borrarVacias(dtdExterna);
        }
    }

    private void cargarReglaInterna(final String regla) {
        int idx0 = regla.indexOf("[") + 1;
        int idx1 = regla.indexOf("]");

        if (idx0 != -1 && idx1 != -1) {
            String[] aEditar = {regla.substring(idx0, idx1).trim()};
            aEditar = separarEspacios(aEditar);
            aEditar = separaRetornoLinea(aEditar);
            aEditar = separarMayorMenor(aEditar);
            aEditar = borrarVacias(aEditar);
            this.dtdInterna = aEditar;
        }
    }

    private String[] separarMayorMenor(final String[] aSeparar) {
        ArrayList<String> resultado = new ArrayList<String>();

        for (int i = 0; i < aSeparar.length; i++) {
            String str = aSeparar[i];
            int idx = str.indexOf("><");
            if (idx != -1) {
                String s0 = str.substring(0, idx + 1);
                String s1 = str.substring(idx + 1, str.length());
                resultado.add(s0);
                resultado.add(s1);
            }
            else {
                resultado.add(str);
            }
        }
        return resultado.toArray(new String[resultado.size()]);
    }

    private String[] separaRetornoLinea(final String[] aSeparar) {
        ArrayList<String> resultado = new ArrayList<String>();

        for (int i = 0; i < aSeparar.length; i++) {
            String str = aSeparar[i];
            String[] separado = StrOp.separar(str, "\n", "", "", '<', '>');
            resultado = (ArrayList)Coleccion.llenar(resultado, separado);
        }
        return resultado.toArray(new String[resultado.size()]);
    }

    private String[] separarEspacios(String[] aSeparar) {
        ArrayList<String> resultado = new ArrayList<String>();

        for (int i = 0; i < aSeparar.length; i++) {
            String str = aSeparar[i];
            String[] separado = StrOp.separar(str, " ", "", "", '<', '>');
            resultado = (ArrayList) Coleccion.llenar(resultado, separado);
        }
        return resultado.toArray(new String[resultado.size()]);
    }
}
